
#原因apriori算法推荐电影

import os
import pandas as pd
data_file = os.path.join('data','ml-small','ratings.csv')

'''
dataset = pd.read_csv(data_file,delimiter='\t',header=None,names=[
    'UserID',
    'MovieID',
    'Rating',
    'Datetime',
])
'''

#跳过第一行原来的列名 重置列名
dataset = pd.read_csv(data_file,skiprows=[0],names=[
    'UserID',
    'MovieID',
    'Rating',
    'Datetime',
])
dataset['Datetime'] = pd.to_datetime(dataset['Datetime'],unit='s') #转换时间 原来的是timestamp (unit='s' 表名单位是秒)

#print(dataset['Datetime'][:5])

#建立特征
dataset['Favorable'] = dataset['Rating'] >= 3 #表示喜欢该电影

#创建训练数据集
x_train = dataset[dataset['UserID'].isin(range(200))]

#喜欢的电影数据
favor_data = dataset[dataset['Favorable']]

#获取每个用户喜欢的电影中看过的
favorable_reviews_by_users = dict((k, frozenset(v.values)) for k, v in favor_data.groupby("UserID")["MovieID"])

#算出每部电影影迷的数量
num_favorable_by_movie = dataset[['MovieID','Favorable']].groupby("MovieID").sum()

#print(num_favor_by_movie[:10])
#实现apriori算法

frequent_itemsets = {}
min_support = 50

#通过集合生成式 创建只包含自己电影id的集合
frequent_itemsets[1] = dict((frozenset((movie_id,)),row["Favorable"]) for movie_id, row in num_favorable_by_movie.iterrows() if row["Favorable"] > min_support)

from collections import defaultdict
import sys

#创建超集，检测频繁程度
def find_frequent_items(favorable_reviews_by_users,k_l_items,min_support):
    counts = defaultdict(int)    
    for user,reviews in favorable_reviews_by_users.items():
        for itemset in k_l_items:
            if itemset.issubset(reviews):
                for other_reviewed_movie in reviews - itemset:
                    current_superset = itemset | frozenset((other_reviewed_movie,))
                    counts[current_superset] += 1
    
    return dict([(itemset,frequency) for itemset,frequency in counts.items() if frequency >= min_support ])


for k in range(2,20):
    
    cur_frequent_itemsets = find_frequent_items(favorable_reviews_by_users,frequent_itemsets[k-1],min_support)
    frequent_itemsets[k] = cur_frequent_itemsets
    if len(cur_frequent_itemsets) == 0: #能找到任何新的频繁项集，就跳出循环
        print("Did not find any frequent itemsets of length {}".format(k))
        sys.stdout.flush()
        break
    else:
        print("I found {} frequent itemsets of length{}".format(len(cur_frequent_itemsets),k))
        sys.stdout.flush()

del frequent_itemsets[1]